home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / lib / xulrunner-1.9.0.14 / chrome / toolkit.jar / content / global / bindings / preferences.xml < prev    next >
Encoding:
Extensible Markup Language  |  2008-10-11  |  45.1 KB  |  1,226 lines

  1. <?xml version="1.0"?>
  2.  
  3. <!DOCTYPE bindings SYSTEM "chrome://global/locale/preferences.dtd">
  4.  
  5. <bindings id="preferencesBindings"
  6.           xmlns="http://www.mozilla.org/xbl"
  7.           xmlns:xbl="http://www.mozilla.org/xbl"
  8.           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  9.  
  10.  
  11.   <binding id="preferences">
  12.     <implementation implements="nsIObserver">
  13.       <method name="observe">
  14.         <parameter name="aSubject"/>
  15.         <parameter name="aTopic"/>
  16.         <parameter name="aData"/>
  17.         <body>
  18.         <![CDATA[
  19.           for (var i = 0; i < this.childNodes.length; ++i) {
  20.             var preference = this.childNodes[i];
  21.             if (preference.name == aData) {
  22.               preference.value = preference.valueFromPreferences;
  23.             }
  24.           }
  25.         ]]>
  26.         </body>
  27.       </method>
  28.       
  29.       <method name="fireChangedEvent">
  30.         <parameter name="aPreference"/>
  31.         <body>
  32.         <![CDATA[
  33.           // Value changed, synthesize an event
  34.           try {
  35.             var event = document.createEvent("Events");
  36.             event.initEvent("change", true, true);
  37.             aPreference.dispatchEvent(event);
  38.           }
  39.           catch (e) {
  40.             Components.utils.reportError(e);
  41.           }
  42.         ]]>
  43.         </body>
  44.       </method>
  45.       
  46.       <field name="service">
  47.         Components.classes["@mozilla.org/preferences-service;1"]
  48.                   .getService(Components.interfaces.nsIPrefService);
  49.       </field>
  50.       <field name="rootBranch">
  51.         Components.classes["@mozilla.org/preferences-service;1"]
  52.                   .getService(Components.interfaces.nsIPrefBranch);
  53.       </field>
  54.       <field name="defaultBranch">
  55.         this.service.getDefaultBranch("");
  56.       </field>
  57.       <field name="rootBranchInternal">
  58.         Components.classes["@mozilla.org/preferences-service;1"]
  59.                   .getService(Components.interfaces.nsIPrefBranchInternal);
  60.       </field>
  61.     </implementation>
  62.   </binding>
  63.  
  64.   <binding id="preference">
  65.     <implementation>
  66.       <constructor>
  67.       <![CDATA[
  68.         // if the element has been inserted without the name attribute set,
  69.         // we have nothing to do here
  70.         if (!this.name)
  71.           return;
  72.  
  73.         this.preferences.rootBranchInternal
  74.             .addObserver(this.name, this.preferences, false);
  75.         // In non-instant apply mode, we must try and use the last saved state
  76.         // from any previous opens of a child dialog instead of the value from
  77.         // preferences, to pick up any edits a user may have made. 
  78.         if (document.documentElement.type == "child" && 
  79.             !this.instantApply && window.opener) {
  80.           var pdoc = window.opener.document;
  81.  
  82.           // Try to find a preference element for the same preference.
  83.           var preference = null;
  84.           var parentPreferences = pdoc.getElementsByTagName("preferences");
  85.           for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
  86.             var parentPrefs = parentPreferences[k]
  87.                                     .getElementsByAttribute("name", this.name);
  88.             for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
  89.               if (parentPrefs[l].localName == "preference")
  90.                 preference = parentPrefs[l];
  91.             }
  92.           }
  93.           this._setValue(preference ? preference.value 
  94.                                     : this.valueFromPreferences, false);
  95.         }
  96.         else
  97.           this._setValue(this.valueFromPreferences, false);
  98.       ]]>
  99.       </constructor>
  100.       <destructor>
  101.         this.preferences.rootBranchInternal
  102.             .removeObserver(this.name, this.preferences);
  103.       </destructor>
  104.       
  105.       <property name="instantApply">
  106.         <getter>
  107.           return this.getAttribute("instantApply") == "true" || document.documentElement.instantApply;
  108.         </getter>
  109.       </property>
  110.  
  111.       <property name="preferences" onget="return this.parentNode"/>
  112.       <property name="name" onget="return this.getAttribute('name');">
  113.         <setter>
  114.           if (val == this.name)
  115.             return val;
  116.             
  117.           this.preferences.rootBranchInternal
  118.               .removeObserver(this.name, this.preferences);
  119.           this.setAttribute('name', val);
  120.           this.preferences.rootBranchInternal
  121.               .addObserver(val, this.preferences, false);
  122.               
  123.           return val;
  124.         </setter>
  125.       </property>
  126.       <property name="type" onget="return this.getAttribute('type');"
  127.                             onset="this.setAttribute('type', val); return val;"/>
  128.       <property name="inverted" onget="return this.getAttribute('inverted') == 'true';"
  129.                                 onset="this.setAttribute('inverted', val); return val;"/>
  130.       <property name="readonly" onget="return this.getAttribute('readonly') == 'true';"
  131.                                 onset="this.setAttribute('readonly', val); return val;"/>
  132.  
  133.       <field name="_value">null</field>
  134.       <method name="_setValue">
  135.         <parameter name="aValue"/>
  136.         <parameter name="aUpdate"/>
  137.         <body>
  138.         <![CDATA[
  139.           if (aUpdate && this.value !== aValue) {
  140.             this._value = aValue;
  141.             if (this.instantApply)
  142.               this.valueFromPreferences = aValue;
  143.             this.preferences.fireChangedEvent(this);
  144.           }
  145.           else if (!aUpdate) {
  146.             this._value = aValue;
  147.             this.updateElements();
  148.           }
  149.           return aValue;
  150.         ]]>
  151.         </body>
  152.       </method>
  153.       <property name="value" onget="return this._value" onset="return this._setValue(val, true);"/>
  154.       
  155.       <property name="locked">
  156.         <getter>
  157.           return this.preferences.rootBranch.prefIsLocked(this.name);
  158.         </getter>
  159.       </property>
  160.       
  161.       <property name="disabled">
  162.         <getter>
  163.           return this.getAttribute("disabled") == "true";
  164.         </getter>
  165.         <setter>
  166.         <![CDATA[
  167.           if (val) 
  168.             this.setAttribute("disabled", "true");
  169.           else
  170.             this.removeAttribute("disabled");
  171.  
  172.           if (!this.id)
  173.             return val;
  174.  
  175.           var elements = document.getElementsByAttribute("preference", this.id);
  176.           for (var i = 0; i < elements.length; ++i) {
  177.             elements[i].disabled = val;
  178.             
  179.             var labels = document.getElementsByAttribute("control", elements[i].id);
  180.             for (var j = 0; j < labels.length; ++j)
  181.               labels[j].disabled = val;
  182.           }
  183.             
  184.           return val;
  185.         ]]>
  186.         </setter>
  187.       </property>
  188.       
  189.       <property name="tabIndex">
  190.         <getter>
  191.           return parseInt(this.getAttribute("tabindex"));
  192.         </getter>
  193.         <setter>
  194.         <![CDATA[
  195.           if (val) 
  196.             this.setAttribute("tabindex", val);
  197.           else
  198.             this.removeAttribute("tabindex");
  199.  
  200.           if (!this.id)
  201.             return val;
  202.  
  203.           var elements = document.getElementsByAttribute("preference", this.id);
  204.           for (var i = 0; i < elements.length; ++i) {
  205.             elements[i].tabIndex = val;
  206.             
  207.             var labels = document.getElementsByAttribute("control", elements[i].id);
  208.             for (var j = 0; j < labels.length; ++j)
  209.               labels[j].tabIndex = val;
  210.           }
  211.             
  212.           return val;
  213.         ]]>
  214.         </setter>
  215.       </property>
  216.  
  217.       <property name="hasUserValue">
  218.         <getter>
  219.         <![CDATA[
  220.           return this.preferences.rootBranch.prefHasUserValue(this.name) &&
  221.                  this.value !== undefined;
  222.         ]]>
  223.         </getter>
  224.       </property>
  225.       
  226.       <method name="reset">
  227.         <body>
  228.           // defer reset until preference update
  229.           this.value = undefined;
  230.         </body>
  231.       </method>
  232.  
  233.       <field name="_useDefault">false</field>      
  234.       <property name="defaultValue">
  235.         <getter>
  236.         <![CDATA[
  237.           this._useDefault = true;
  238.           var val = this.valueFromPreferences;
  239.           this._useDefault = false;
  240.           return val;
  241.         ]]>
  242.         </getter>
  243.       </property>
  244.       
  245.       <property name="_branch">
  246.         <getter>
  247.           return this._useDefault ? this.preferences.defaultBranch : this.preferences.rootBranch;
  248.         </getter>
  249.       </property>
  250.       
  251.       <field name="batching">false</field>
  252.       
  253.       <method name="_reportUnknownType">
  254.         <body>
  255.         <![CDATA[
  256.           var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
  257.                                          .getService(Components.interfaces.nsIConsoleService);
  258.           var msg = "<preference> with id='" + this.id + "' and name='" + 
  259.                     this.name + "' has unknown type '" + this.type + "'.";
  260.           consoleService.logStringMessage(msg);
  261.         ]]>
  262.         </body>
  263.       </method>
  264.       
  265.       <property name="valueFromPreferences">
  266.         <getter>
  267.         <![CDATA[
  268.           try {
  269.             // Force a resync of value with preferences.
  270.             switch (this.type) {
  271.             case "int":
  272.               return this._branch.getIntPref(this.name);
  273.             case "bool":
  274.               var val = this._branch.getBoolPref(this.name);
  275.               return this.inverted ? !val : val;
  276.             case "wstring":
  277.               return this._branch
  278.                          .getComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString)
  279.                          .data;
  280.             case "string":
  281.             case "unichar":
  282.               return this._branch
  283.                          .getComplexValue(this.name, Components.interfaces.nsISupportsString)
  284.                          .data;
  285.             case "fontname":
  286.               var family = this._branch
  287.                                .getComplexValue(this.name, Components.interfaces.nsISupportsString)
  288.                                .data;
  289.               var fontEnumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"]
  290.                                              .createInstance(Components.interfaces.nsIFontEnumerator);
  291.               return fontEnumerator.getStandardFamilyName(family);
  292.             case "file":
  293.               var f = this._branch
  294.                           .getComplexValue(this.name, Components.interfaces.nsILocalFile);
  295.               return f;
  296.             default:
  297.               this._reportUnknownType();
  298.             }
  299.           }
  300.           catch (e) { }
  301.           return null;
  302.         ]]>
  303.         </getter>
  304.         <setter>
  305.         <![CDATA[
  306.           // Exit early if nothing to do.
  307.           if (this.readonly || this.valueFromPreferences == val)
  308.             return val;
  309.  
  310.           // The special value undefined means 'reset preference to default'.
  311.           if (val === undefined) {
  312.             this.preferences.rootBranch.clearUserPref(this.name);
  313.             return val;
  314.           }
  315.  
  316.           // Force a resync of preferences with value.
  317.           switch (this.type) {
  318.           case "int":
  319.             this.preferences.rootBranch.setIntPref(this.name, val);
  320.             break;
  321.           case "bool":
  322.             this.preferences.rootBranch.setBoolPref(this.name, this.inverted ? !val : val);
  323.             break;
  324.           case "wstring":
  325.             var pls = Components.classes["@mozilla.org/pref-localizedstring;1"]
  326.                                 .createInstance(Components.interfaces.nsIPrefLocalizedString);
  327.             pls.data = val;
  328.             this.preferences.rootBranch
  329.                 .setComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString, pls);
  330.             break;
  331.           case "string":
  332.           case "unichar":
  333.           case "fontname":
  334.             var iss = Components.classes["@mozilla.org/supports-string;1"]
  335.                                 .createInstance(Components.interfaces.nsISupportsString);
  336.             iss.data = val;
  337.             this.preferences.rootBranch
  338.                 .setComplexValue(this.name, Components.interfaces.nsISupportsString, iss);
  339.             break;
  340.           case "file":
  341.             var lf;
  342.             if (typeof(val) == "string") {
  343.               lf = Components.classes["@mozilla.org/file/local;1"]
  344.                              .createInstance(Components.interfaces.nsILocalFile);
  345.               lf.persistentDescriptor = val;
  346.               if (!lf.exists())
  347.                 lf.initWithPath(val);
  348.             }
  349.             else 
  350.               lf = val.QueryInterface(Components.interfaces.nsILocalFile);
  351.             this.preferences.rootBranch
  352.                 .setComplexValue(this.name, Components.interfaces.nsILocalFile, lf);
  353.             break;
  354.           default:
  355.             this._reportUnknownType();
  356.           }
  357.           if (!this.batching)
  358.             this.preferences.service.savePrefFile(null);
  359.           return val;
  360.         ]]>
  361.         </setter>
  362.       </property>
  363.       
  364.       <method name="setElementValue">
  365.         <parameter name="aElement"/>
  366.         <body>
  367.         <![CDATA[
  368.           if (this.locked)
  369.             aElement.disabled = true;
  370.  
  371.           if (!this.isElementEditable(aElement))
  372.             return;
  373.  
  374.           var rv = undefined;
  375.           if (aElement.hasAttribute("onsyncfrompreference")) {
  376.             // Value changed, synthesize an event
  377.             try {
  378.               var event = document.createEvent("Events");
  379.               event.initEvent("syncfrompreference", true, true);
  380.               var f = new Function ("event", 
  381.                                     aElement.getAttribute("onsyncfrompreference"));
  382.               rv = f.call(aElement, event);
  383.             }
  384.             catch (e) {
  385.               Components.utils.reportError(e);
  386.             }
  387.           }
  388.           var val = rv !== undefined ? rv : (this.instantApply ? this.valueFromPreferences : this.value);
  389.           // if the preference is marked for reset, show default value in UI
  390.           if (val === undefined)
  391.             val = this.defaultValue;
  392.  
  393.           /**
  394.            * Initialize a UI element property with a value. Handles the case 
  395.            * where an element has not yet had a XBL binding attached for it and
  396.            * the property setter does not yet exist by setting the same attribute
  397.            * on the XUL element using DOM apis and assuming the element's 
  398.            * constructor or property getters appropriately handle this state. 
  399.            */
  400.           function setValue(element, attribute, value) {
  401.             if (attribute in element) 
  402.               element[attribute] = value;
  403.             else
  404.               element.setAttribute(attribute, value);
  405.           }
  406.           if (aElement.localName == "checkbox" ||
  407.               aElement.localName == "listitem")
  408.             setValue(aElement, "checked", val);
  409.           else if (aElement.localName == "colorpicker")
  410.             setValue(aElement, "color", val);
  411.           else if (aElement.localName == "textbox") {
  412.             // XXXmano Bug 303998: Avoid a caret placement issue if either the
  413.             // preference observer or its setter calls updateElements as a result
  414.             // of the input event handler.
  415.             if (aElement.value !== val)
  416.               setValue(aElement, "value", val);
  417.           }
  418.           else
  419.             setValue(aElement, "value", val);
  420.         ]]>
  421.         </body>
  422.       </method>
  423.  
  424.       <method name="getElementValue">
  425.         <parameter name="aElement"/>
  426.         <body>
  427.         <![CDATA[
  428.           if (aElement.hasAttribute("onsynctopreference")) {
  429.             // Value changed, synthesize an event
  430.             try {
  431.               var event = document.createEvent("Events");
  432.               event.initEvent("synctopreference", true, true);
  433.               var f = new Function ("event", 
  434.                                     aElement.getAttribute("onsynctopreference"));
  435.               var rv = f.call(aElement, event);
  436.               if (rv !== undefined) 
  437.                 return rv;
  438.             }
  439.             catch (e) {
  440.               Components.utils.reportError(e);
  441.             }
  442.           }
  443.           
  444.           /**
  445.            * Read the value of an attribute from an element, assuming the 
  446.            * attribute is a property on the element's node API. If the property
  447.            * is not present in the API, then assume its value is contained in
  448.            * an attribute, as is the case before a binding has been attached.
  449.            */
  450.           function getValue(element, attribute) {
  451.             if (attribute in element)
  452.               return element[attribute];
  453.             return element.getAttribute(attribute);
  454.           }
  455.           if (aElement.localName == "checkbox" ||
  456.               aElement.localName == "listitem")
  457.             var value = getValue(aElement, "checked");
  458.           else if (aElement.localName == "colorpicker")
  459.             value = getValue(aElement, "color");
  460.           else
  461.             value = getValue(aElement, "value");
  462.  
  463.           switch (this.type) {
  464.           case "int":
  465.             var intValue = parseInt(value, 10) + '';
  466.             return intValue != "NaN" ? intValue : 0;
  467.           case "bool":
  468.             return typeof(value) == "boolean" ? value : value == "true";
  469.           }
  470.           return value;
  471.         ]]>
  472.         </body>
  473.       </method>
  474.       
  475.       <method name="isElementEditable">
  476.         <parameter name="aElement"/>
  477.         <body>
  478.         <![CDATA[
  479.           switch (aElement.localName) {
  480.           case "checkbox":
  481.           case "colorpicker":
  482.           case "radiogroup":
  483.           case "textbox":
  484.           case "listitem":
  485.           case "listbox":
  486.           case "menulist":
  487.             return true;
  488.           }
  489.           return aElement.getAttribute("preference-editable") == "true";
  490.         ]]> 
  491.         </body>
  492.       </method>
  493.       
  494.       <method name="updateElements">
  495.         <body>
  496.         <![CDATA[
  497.           if (!this.id)
  498.             return;
  499.  
  500.           // This "change" event handler tracks changes made to preferences by 
  501.           // sources other than the user in this window. 
  502.           var elements = document.getElementsByAttribute("preference", this.id);
  503.           for (var i = 0; i < elements.length; ++i) 
  504.             this.setElementValue(elements[i]);
  505.         ]]>
  506.         </body>
  507.       </method>
  508.     </implementation>
  509.     
  510.     <handlers>
  511.       <handler event="change">
  512.         this.updateElements();
  513.       </handler>
  514.     </handlers>
  515.   </binding>
  516.  
  517.   <binding id="prefwindow"
  518.            extends="chrome://global/content/bindings/dialog.xml#dialog">
  519.     <resources>
  520.       <stylesheet src="chrome://global/skin/preferences.css"/>
  521.     </resources>
  522.     <content dlgbuttons="accept,cancel" persist="lastSelected screenX screenY"
  523.              closebuttonlabel="&preferencesCloseButton.label;"
  524.              closebuttonaccesskey="&preferencesCloseButton.accesskey;"
  525.              role="dialog"
  526.              title="&preferencesDefaultTitleMac.title;">
  527.       <xul:radiogroup anonid="selector" orient="horizontal" class="paneSelector chromeclass-toolbar"
  528.                       role="listbox"/> <!-- Expose to accessibility APIs as a listbox -->
  529.       <xul:hbox flex="1" class="paneDeckContainer">
  530.         <xul:deck anonid="paneDeck" flex="1">
  531.           <children includes="prefpane"/>
  532.         </xul:deck>
  533.       </xul:hbox>
  534.       <xul:hbox anonid="dlg-buttons" class="prefWindow-dlgbuttons"
  535.                 >
  536.         <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
  537.         <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
  538.         <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
  539.         <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
  540.         <xul:spacer anonid="spacer" flex="1"/>
  541.         <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
  542.         <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
  543.       </xul:hbox>
  544.       <xul:hbox>
  545.         <children/>
  546.       </xul:hbox>
  547.     </content>
  548.     <implementation implements="nsITimerCallback">
  549.       <constructor>
  550.       <![CDATA[
  551.         if (this.type != "child") {
  552.           var psvc = Components.classes["@mozilla.org/preferences-service;1"]
  553.                                .getService(Components.interfaces.nsIPrefBranch);
  554.           this.instantApply = psvc.getBoolPref("browser.preferences.instantApply");
  555.           if (this.instantApply) {
  556.             var docElt = document.documentElement;
  557.             var acceptButton = docElt.getButton("accept");
  558.             acceptButton.hidden = true;
  559.             var cancelButton  = docElt.getButton("cancel");
  560.             // morph the Cancel button into the Close button
  561.             cancelButton.setAttribute ("icon", "close");
  562.             cancelButton.label = docElt.getAttribute("closebuttonlabel");
  563.             cancelButton.accesskey = docElt.getAttribute("closebuttonaccesskey");
  564.           }
  565.         }
  566.         this.setAttribute("animated", this._shouldAnimate ? "true" : "false");
  567.         var panes = this.preferencePanes;
  568.  
  569.         var lastPane = null;
  570.         if (this.lastSelected) {
  571.           lastPane = document.getElementById(this.lastSelected);
  572.           if (!lastPane) {
  573.             this.lastSelected = null;
  574.           }
  575.         }
  576.  
  577.         var paneToLoad;
  578.         if ("arguments" in window && window.arguments[0] && document.getElementById(window.arguments[0]) && document.getElementById(window.arguments[0]).nodeName == "prefpane") {
  579.           paneToLoad = document.getElementById(window.arguments[0]);
  580.           this.lastSelected = paneToLoad.id;
  581.         }
  582.         else if (lastPane)
  583.           paneToLoad = lastPane;
  584.         else
  585.           paneToLoad = panes[0];
  586.  
  587.         for (var i = 0; i < panes.length; ++i) {
  588.           this._makePaneButton(panes[i]);
  589.           if (panes[i].loaded) {
  590.             // Inline pane content, fire load event to force initialization.
  591.             this._fireEvent("paneload", panes[i]);
  592.           }
  593.         }
  594.         this.showPane(paneToLoad);
  595.  
  596.         if (panes.length == 1)
  597.           this._selector.setAttribute("collapsed", "true");
  598.       ]]>
  599.       </constructor>
  600.  
  601.       <destructor>
  602.       <![CDATA[
  603.         // Release timers to avoid reference cycles.
  604.         if (this._animateTimer) {
  605.           this._animateTimer.cancel();
  606.           this._animateTimer = null;
  607.         }
  608.         if (this._fadeTimer) {
  609.           this._fadeTimer.cancel();
  610.           this._fadeTimer = null;
  611.         }
  612.       ]]>
  613.       </destructor>
  614.  
  615.       <field name="instantApply">false</field>
  616.       
  617.       <property name="preferencePanes"
  618.                 onget="return this.getElementsByTagName('prefpane');"/>
  619.  
  620.       <property name="type" onget="return this.getAttribute('type');"/>
  621.       <property name="_paneDeck"
  622.                 onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'paneDeck');"/>
  623.       <property name="_paneDeckContainer"
  624.                 onget="return document.getAnonymousElementByAttribute(this, 'class', 'paneDeckContainer');"/>
  625.       <property name="_selector"
  626.                 onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'selector');"/>
  627.       <property name="lastSelected" 
  628.                 onget="return this.getAttribute('lastSelected');">
  629.         <setter>
  630.           this.setAttribute("lastSelected", val); 
  631.           document.persist(this.id, "lastSelected");
  632.           return val;
  633.         </setter>          
  634.       </property>
  635.       <property name="currentPane"
  636.                 onset="return this._currentPane = val;">
  637.         <getter>
  638.           if (!this._currentPane)
  639.             this._currentPane = this.preferencePanes[0];
  640.           
  641.           return this._currentPane;
  642.         </getter> 
  643.       </property>
  644.       <field name="_currentPane">null</field>
  645.       
  646.       
  647.       <method name="_makePaneButton">
  648.         <parameter name="aPaneElement"/>
  649.         <body>
  650.         <![CDATA[
  651.           var radio = document.createElement("radio");
  652.           radio.setAttribute("pane", aPaneElement.id);
  653.           radio.setAttribute("label", aPaneElement.label);
  654.           // Expose preference group choice to accessibility APIs as an unchecked list item
  655.           // The parent group is exposed to accessibility APIs as a list
  656.           if (aPaneElement.image)
  657.             radio.setAttribute("src", aPaneElement.image);
  658.           radio.style.listStyleImage = aPaneElement.style.listStyleImage;
  659.           this._selector.appendChild(radio);
  660.           return radio;
  661.         ]]>
  662.         </body>
  663.       </method>
  664.  
  665.       <method name="showPane">
  666.         <parameter name="aPaneElement"/>
  667.         <body>
  668.         <![CDATA[
  669.           if (!aPaneElement)
  670.             return;
  671.  
  672.           this._selector.selectedItem = document.getAnonymousElementByAttribute(this, "pane", aPaneElement.id);
  673.           if (!aPaneElement.loaded) {
  674.             function OverlayLoadObserver(aPane)
  675.             {
  676.               this._pane = aPane;
  677.             }
  678.             OverlayLoadObserver.prototype = { 
  679.               _outer: this,
  680.               observe: function (aSubject, aTopic, aData) 
  681.               {
  682.                 this._pane.loaded = true;
  683.                 this._outer._fireEvent("paneload", this._pane);
  684.                 this._outer._selectPane(this._pane);
  685.               }
  686.             };
  687.             
  688.             var obs = new OverlayLoadObserver(aPaneElement);
  689.             document.loadOverlay(aPaneElement.src, obs);
  690.           }
  691.           else
  692.             this._selectPane(aPaneElement);
  693.         ]]>
  694.         </body>
  695.       </method>
  696.       
  697.       <method name="_fireEvent">
  698.         <parameter name="aEventName"/>
  699.         <parameter name="aTarget"/>
  700.         <body>
  701.         <![CDATA[
  702.           // Panel loaded, synthesize a load event. 
  703.           try {
  704.             var event = document.createEvent("Events");
  705.             event.initEvent(aEventName, true, true);
  706.             var cancel = !aTarget.dispatchEvent(event);
  707.             if (aTarget.hasAttribute("on" + aEventName)) {
  708.               var fn = new Function ("event", aTarget.getAttribute("on" + aEventName));
  709.               var rv = fn.call(aTarget, event);
  710.               if (rv == false)
  711.                 cancel = true;
  712.             }
  713.             return !cancel;  
  714.           }
  715.           catch (e) { 
  716.             Components.utils.reportError(e);
  717.           }
  718.           return false;
  719.         ]]>
  720.         </body>
  721.       </method>
  722.       
  723.       <field name="_initialized">false</field>
  724.       <method name="_selectPane">
  725.         <parameter name="aPaneElement"/>
  726.         <body>
  727.         <![CDATA[
  728.           var helpButton = document.documentElement.getButton("help");
  729.           if (aPaneElement.helpTopic)
  730.             helpButton.hidden = false;
  731.           else
  732.             helpButton.hidden = true;
  733.  
  734.           // Find this pane's index in the deck and set the deck's 
  735.           // selectedIndex to that value to switch to it.
  736.           var prefpanes = this.preferencePanes;
  737.           for (var i = 0; i < prefpanes.length; ++i) {
  738.             if (prefpanes[i] == aPaneElement) {
  739.               this._paneDeck.selectedIndex = i;
  740.               
  741.               if (this.type != "child") {
  742.                 if (aPaneElement.hasAttribute("flex") && this._shouldAnimate &&
  743.                     prefpanes.length > 1)
  744.                   aPaneElement.removeAttribute("flex");
  745.                 // Calling sizeToContent after the first prefpane is loaded
  746.                 // will size the windows contents so style information is
  747.                 // available to calculate correct sizing.
  748.                 if (!this._initialized && prefpanes.length > 1) {
  749.                   if (this._shouldAnimate)
  750.                     this.style.minHeight = 0;
  751.                   window.sizeToContent();
  752.                 }
  753.  
  754.                 var oldPane = this.lastSelected ? document.getElementById(this.lastSelected) : this.preferencePanes[0];
  755.                 oldPane.selected = !(aPaneElement.selected = true);
  756.                 this.lastSelected = aPaneElement.id;
  757.                 this.currentPane = aPaneElement;
  758.                 this._initialized = true;
  759.  
  760.                 // Only animate if we've switched between prefpanes
  761.                 if (this._shouldAnimate && oldPane.id != aPaneElement.id) {
  762.                   aPaneElement.style.opacity = 0.0;
  763.                   this.animate(oldPane, aPaneElement);
  764.                 }
  765.                 else if (!this._shouldAnimate && prefpanes.length > 1) {
  766.                   var targetHeight = parseInt(window.getComputedStyle(this._paneDeckContainer, "").height);
  767.                   var verticalPadding = parseInt(window.getComputedStyle(aPaneElement, "").paddingTop);
  768.                   verticalPadding += parseInt(window.getComputedStyle(aPaneElement, "").paddingBottom);
  769.                   if (aPaneElement.contentHeight > targetHeight - verticalPadding) {
  770.                     // To workaround the bottom border of a groupbox from being
  771.                     // cutoff an hbox with a class of bottomBox may enclose it.
  772.                     // This needs to include its padding to resize properly.
  773.                     // See bug 394433
  774.                     var bottomPadding = 0;
  775.                     var bottomBox = aPaneElement.getElementsByAttribute("class", "bottomBox")[0];
  776.                     if (bottomBox)
  777.                       bottomPadding = parseInt(window.getComputedStyle(bottomBox, "").paddingBottom);
  778.                     window.innerHeight += bottomPadding + verticalPadding + aPaneElement.contentHeight - targetHeight;
  779.                   }
  780.  
  781.                   // XXX rstrong - extend the contents of the prefpane to
  782.                   // prevent elements from being cutoff (see bug 349098).
  783.                   if (aPaneElement.contentHeight + verticalPadding < targetHeight)
  784.                     aPaneElement._content.style.height = targetHeight - verticalPadding + "px";
  785.                 }
  786.               }
  787.               break;
  788.             }
  789.           }
  790.         ]]>
  791.         </body>
  792.       </method>
  793.       
  794.       <property name="_shouldAnimate">
  795.         <getter>
  796.         <![CDATA[
  797.           var psvc = Components.classes["@mozilla.org/preferences-service;1"]
  798.                                .getService(Components.interfaces.nsIPrefBranch);
  799.           var animate = false;
  800.           try {
  801.             animate = psvc.getBoolPref("browser.preferences.animateFadeIn");
  802.           }
  803.           catch (e) { }
  804.           return animate;
  805.         ]]>
  806.         </getter>
  807.       </property>
  808.       
  809.       <method name="animate">
  810.         <parameter name="aOldPane"/>
  811.         <parameter name="aNewPane"/>
  812.         <body>
  813.         <![CDATA[
  814.           // if we are already resizing, use currentHeight
  815.           var oldHeight = this._currentHeight ? this._currentHeight : aOldPane.contentHeight;
  816.           
  817.           this._multiplier = aNewPane.contentHeight > oldHeight ? 1 : -1;
  818.           var sizeDelta = Math.abs(oldHeight - aNewPane.contentHeight);
  819.           this._animateRemainder = sizeDelta % this._animateIncrement;
  820.  
  821.           this._setUpAnimationTimer(oldHeight);
  822.         ]]>
  823.         </body>
  824.       </method>
  825.       
  826.       <property name="_sizeIncrement">
  827.         <getter>
  828.         <![CDATA[
  829.           var lastSelectedPane = document.getElementById(this.lastSelected);
  830.           var increment = this._animateIncrement * this._multiplier;
  831.           var newHeight = this._currentHeight + increment;
  832.           if ((this._multiplier > 0 && this._currentHeight >= lastSelectedPane.contentHeight) ||
  833.               (this._multiplier < 0 && this._currentHeight <= lastSelectedPane.contentHeight))
  834.             return 0;
  835.           
  836.           if ((this._multiplier > 0 && newHeight > lastSelectedPane.contentHeight) ||
  837.               (this._multiplier < 0 && newHeight < lastSelectedPane.contentHeight))
  838.             increment = this._animateRemainder * this._multiplier;
  839.           return increment;
  840.         ]]>
  841.         </getter>
  842.       </property>
  843.       
  844.       <method name="notify">
  845.         <parameter name="aTimer"/>
  846.         <body>
  847.         <![CDATA[
  848.           if (!document)
  849.             aTimer.cancel();
  850.           
  851.           if (aTimer == this._animateTimer) {
  852.             var increment = this._sizeIncrement;
  853.             if (increment != 0) {
  854.               window.innerHeight += increment;
  855.               this._currentHeight += increment;
  856.             }
  857.             else {
  858.               aTimer.cancel();
  859.               this._setUpFadeTimer();
  860.             }
  861.           } else if (aTimer == this._fadeTimer) {
  862.             var elt = document.getElementById(this.lastSelected);
  863.             var newOpacity = parseFloat(window.getComputedStyle(elt, "").opacity) + this._fadeIncrement;
  864.             if (newOpacity < 1.0)
  865.               elt.style.opacity = newOpacity;
  866.             else {
  867.               aTimer.cancel();
  868.               elt.style.opacity = 1.0;
  869.             }
  870.           }
  871.         ]]>
  872.         </body>
  873.       </method>
  874.       
  875.       <method name="_setUpAnimationTimer">
  876.         <parameter name="aStartHeight"/>
  877.         <body>
  878.         <![CDATA[
  879.           if (!this._animateTimer) 
  880.             this._animateTimer = Components.classes["@mozilla.org/timer;1"]
  881.                                            .createInstance(Components.interfaces.nsITimer);
  882.           else
  883.             this._animateTimer.cancel();
  884.           this._currentHeight = aStartHeight;
  885.           
  886.           this._animateTimer.initWithCallback(this, this._animateDelay, 
  887.                                               Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
  888.         ]]>
  889.         </body>
  890.       </method>
  891.       
  892.       <method name="_setUpFadeTimer">
  893.         <body>
  894.         <![CDATA[
  895.           if (!this._fadeTimer) 
  896.             this._fadeTimer = Components.classes["@mozilla.org/timer;1"]
  897.                                         .createInstance(Components.interfaces.nsITimer);
  898.           else
  899.             this._fadeTimer.cancel();
  900.           
  901.           this._fadeTimer.initWithCallback(this, this._fadeDelay, 
  902.                                            Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
  903.         ]]>
  904.         </body>
  905.       </method>
  906.       
  907.       <field name="_animateTimer">null</field>
  908.       <field name="_fadeTimer">null</field>
  909.       <field name="_animateDelay">15</field>
  910.       <field name="_animateIncrement">40</field>
  911.       <field name="_fadeDelay">5</field>
  912.       <field name="_fadeIncrement">0.40</field>
  913.       <field name="_animateRemainder">0</field>
  914.       <field name="_currentHeight">0</field>
  915.       <field name="_multiplier">0</field>
  916.  
  917.       <method name="addPane">
  918.         <parameter name="aPaneElement"/>
  919.         <body>
  920.         <![CDATA[
  921.           this.appendChild(aPaneElement);
  922.           
  923.           // Set up pane button
  924.           this._makePaneButton(aPaneElement);
  925.         ]]>
  926.         </body>
  927.       </method>
  928.       
  929.       <method name="openSubDialog">
  930.         <parameter name="aURL"/>
  931.         <parameter name="aFeatures"/>
  932.         <parameter name="aParams"/>
  933.         <body>
  934.           return openDialog(aURL, "", "modal,centerscreen,resizable=no" + (aFeatures != "" ? ("," + aFeatures) : ""), aParams);
  935.         </body>
  936.       </method>
  937.       
  938.       <method name="openWindow">
  939.         <parameter name="aWindowType"/>
  940.         <parameter name="aURL"/>
  941.         <parameter name="aFeatures"/>
  942.         <parameter name="aParams"/>
  943.         <body>
  944.         <![CDATA[
  945.           var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
  946.                              .getService(Components.interfaces.nsIWindowMediator);
  947.           var win = aWindowType ? wm.getMostRecentWindow(aWindowType) : null;
  948.           if (win) {
  949.             if ("initWithParams" in win)
  950.               win.initWithParams(aParams);
  951.             win.focus();
  952.           }
  953.           else {
  954.             var features = "resizable,dialog=no,centerscreen" + (aFeatures != "" ? ("," + aFeatures) : "");
  955.             var parentWindow = (this.instantApply || !window.opener || window.opener.closed) ? window : window.opener;
  956.             win = parentWindow.openDialog(aURL, "_blank", features, aParams);
  957.           }
  958.           return win;
  959.         ]]>
  960.         </body>
  961.       </method>
  962.     </implementation>
  963.     <handlers>
  964.       <handler event="dialogaccept">
  965.       <![CDATA[
  966.         if (!this._fireEvent("beforeaccept", this)) 
  967.           return;
  968.         
  969.         if (this.type == "child" && window.opener) {
  970.           var psvc = Components.classes["@mozilla.org/preferences-service;1"]
  971.                                .getService(Components.interfaces.nsIPrefBranch);
  972.           var instantApply = psvc.getBoolPref("browser.preferences.instantApply");
  973.           if (instantApply) {
  974.             var panes = this.preferencePanes;
  975.             for (var i = 0; i < panes.length; ++i)
  976.               panes[i].writePreferences(true);
  977.           }
  978.           else {
  979.             // Clone all the preferences elements from the child document and
  980.             // insert them into the pane collection of the parent. 
  981.             var pdoc = window.opener.document;
  982.             if (pdoc.documentElement.localName == "prefwindow") {
  983.               var currentPane = pdoc.documentElement.currentPane;
  984.               var id = window.location.href + "#childprefs";
  985.               var childPrefs = pdoc.getElementById(id);
  986.               if (!childPrefs) {
  987.                 var childPrefs = pdoc.createElement("preferences");
  988.                 currentPane.appendChild(childPrefs);
  989.                 childPrefs.id = id;
  990.               }
  991.               var panes = this.preferencePanes;
  992.               for (var i = 0; i < panes.length; ++i) {
  993.                 var preferences = panes[i].preferences;
  994.                 for (var j = 0; j < preferences.length; ++j) {
  995.                   // Try to find a preference element for the same preference.
  996.                   var preference = null;
  997.                   var parentPreferences = pdoc.getElementsByTagName("preferences");
  998.                   for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
  999.                     var parentPrefs = parentPreferences[k]
  1000.                                          .getElementsByAttribute("name", preferences[j].name);
  1001.                     for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
  1002.                       if (parentPrefs[l].localName == "preference")
  1003.                         preference = parentPrefs[l];
  1004.                     }
  1005.                   }
  1006.                   if (!preference) {
  1007.                     // No matching preference in the parent window.
  1008.                     preference = pdoc.createElement("preference");
  1009.                     childPrefs.appendChild(preference);
  1010.                     preference.name     = preferences[j].name;
  1011.                     preference.type     = preferences[j].type;
  1012.                     preference.inverted = preferences[j].inverted;
  1013.                     preference.readonly = preferences[j].readonly;
  1014.                     preference.disabled = preferences[j].disabled;
  1015.                   }
  1016.                   preference.value = preferences[j].value;
  1017.                 }
  1018.               }
  1019.             }
  1020.           }
  1021.         }
  1022.         else {
  1023.           var panes = this.preferencePanes;
  1024.           for (var i = 0; i < panes.length; ++i)
  1025.             panes[i].writePreferences(false);
  1026.  
  1027.           var psvc = Components.classes["@mozilla.org/preferences-service;1"]
  1028.                                .getService(Components.interfaces.nsIPrefService);
  1029.           psvc.savePrefFile(null);
  1030.         }
  1031.       ]]>
  1032.       </handler>
  1033.       <handler event="command">
  1034.         if (event.originalTarget.hasAttribute("pane")) {
  1035.           var pane = document.getElementById(event.originalTarget.getAttribute("pane"));
  1036.           event.originalTarget.parentNode.parentNode.showPane(pane);
  1037.         }
  1038.       </handler>
  1039.  
  1040.       <handler event="keypress" key="&windowClose.key;" modifiers="accel" phase="capturing">
  1041.         if (this.instantApply)
  1042.           window.close();
  1043.       </handler>
  1044.     </handlers>
  1045.   </binding>
  1046.   
  1047.   <binding id="prefpane">
  1048.     <resources>
  1049.       <stylesheet src="chrome://global/skin/preferences.css"/>
  1050.     </resources>
  1051.     <content>
  1052.       <xul:vbox class="content-box" xbl:inherits="flex">
  1053.         <children/>
  1054.       </xul:vbox>
  1055.     </content>
  1056.     <implementation>
  1057.       <method name="writePreferences">
  1058.         <parameter name="aFlushToDisk"/>
  1059.         <body>
  1060.         <![CDATA[
  1061.           // Write all values to preferences.
  1062.           var preferences = this.preferences;
  1063.           for (var i = 0; i < preferences.length; ++i) {
  1064.             var preference = preferences[i];
  1065.             preference.batching = true;
  1066.             preference.valueFromPreferences = preference.value;
  1067.             preference.batching = false;
  1068.           }
  1069.           if (aFlushToDisk) {
  1070.             var psvc = Components.classes["@mozilla.org/preferences-service;1"]
  1071.                                  .getService(Components.interfaces.nsIPrefService);
  1072.             psvc.savePrefFile(null);
  1073.           }
  1074.         ]]>
  1075.         </body>
  1076.       </method>
  1077.       
  1078.       <property name="src" 
  1079.                 onget="return this.getAttribute('src');"
  1080.                 onset="this.setAttribute('src', val); return val;"/>
  1081.       <property name="selected" 
  1082.                 onget="return this.getAttribute('selected') == 'true';"
  1083.                 onset="this.setAttribute('selected', val); return val;"/>
  1084.       <property name="image" 
  1085.                 onget="return this.getAttribute('image');"
  1086.                 onset="this.setAttribute('image', val); return val;"/>
  1087.       <property name="label" 
  1088.                 onget="return this.getAttribute('label');"
  1089.                 onset="this.setAttribute('label', val); return val;"/>
  1090.       
  1091.       <property name="preferenceElements"
  1092.                 onget="return this.getElementsByAttribute('preference', '*');"/>
  1093.       <property name="preferences"
  1094.                 onget="return this.getElementsByTagName('preference');"/>
  1095.  
  1096.       <property name="helpTopic">
  1097.         <getter>
  1098.         <![CDATA[
  1099.           // if there are tabs, and the selected tab provides a helpTopic, return that
  1100.           var box = this.getElementsByTagName("tabbox");
  1101.           if (box[0]) {
  1102.             var tab = box[0].selectedTab;
  1103.             if (tab && tab.hasAttribute("helpTopic"))
  1104.               return tab.getAttribute("helpTopic");
  1105.           }
  1106.  
  1107.           // otherwise, return the helpTopic of the current panel
  1108.           return this.getAttribute("helpTopic");
  1109.         ]]>
  1110.         </getter>
  1111.       </property>
  1112.  
  1113.       <field name="_loaded">false</field>
  1114.       <property name="loaded" 
  1115.                 onget="return !this.src ? true : this._loaded;"
  1116.                 onset="this._loaded = val; return val;"/>
  1117.       
  1118.       <method name="preferenceForElement">
  1119.         <parameter name="aElement"/>
  1120.         <body>
  1121.           return document.getElementById(aElement.getAttribute("preference"));
  1122.         </body>
  1123.       </method>
  1124.       
  1125.       <method name="getPreferenceElement">
  1126.         <parameter name="aStartElement"/>
  1127.         <body>
  1128.         <![CDATA[
  1129.           var temp = aStartElement;
  1130.           while (temp && temp.nodeType == Node.ELEMENT_NODE && 
  1131.                  !temp.hasAttribute("preference"))
  1132.             temp = temp.parentNode;
  1133.           return temp.nodeType == Node.ELEMENT_NODE ? temp : aStartElement;
  1134.         ]]>
  1135.         </body>
  1136.       </method>
  1137.       
  1138.       <method name="userChangedValue">
  1139.         <parameter name="aElement"/>
  1140.         <body>
  1141.         <![CDATA[
  1142.           var element = this.getPreferenceElement(aElement);
  1143.           if (element.hasAttribute("preference")) {
  1144.             var preference = document.getElementById(element.getAttribute("preference"));
  1145.             var prefVal = preference.getElementValue(element);
  1146.             preference.value = prefVal;
  1147.           }
  1148.         ]]>
  1149.         </body>
  1150.       </method>
  1151.       
  1152.       <property name="contentHeight">
  1153.         <getter>
  1154.           var targetHeight = parseInt(window.getComputedStyle(this._content, "").height);
  1155.           targetHeight += parseInt(window.getComputedStyle(this._content, "").marginTop);
  1156.           targetHeight += parseInt(window.getComputedStyle(this._content, "").marginBottom);
  1157.           return targetHeight;
  1158.         </getter>
  1159.       </property>
  1160.       <field name="_content">
  1161.         document.getAnonymousElementByAttribute(this, "class", "content-box");
  1162.       </field>
  1163.     </implementation>
  1164.     <handlers>
  1165.       <handler event="command">
  1166.         // This "command" event handler tracks changes made to preferences by 
  1167.         // the user in this window. 
  1168.         this.userChangedValue(event.target);
  1169.       </handler>
  1170.       <handler event="select">
  1171.         // This "select" event handler tracks changes made to colorpicker 
  1172.         // preferences by the user in this window.
  1173.         if (event.target.localName == "colorpicker") 
  1174.           this.userChangedValue(event.target);
  1175.       </handler>
  1176.       <handler event="change">
  1177.         // This "change" event handler tracks changes made to preferences by 
  1178.         // the user in this window. 
  1179.         this.userChangedValue(event.target);
  1180.       </handler>
  1181.       <handler event="input">
  1182.         // This "input" event handler tracks changes made to preferences by 
  1183.         // the user in this window.
  1184.         this.userChangedValue(event.target);
  1185.       </handler>
  1186.       <handler event="paneload">
  1187.       <![CDATA[
  1188.         // Initialize all values from preferences.
  1189.         var elements = this.preferenceElements;
  1190.         for (var i = 0; i < elements.length; ++i) {
  1191.           try {
  1192.             var preference = this.preferenceForElement(elements[i]);
  1193.             preference.setElementValue(elements[i]);
  1194.           }
  1195.           catch (e) {
  1196.             dump("*** No preference found for " + elements[i].getAttribute("preference") + "\n");
  1197.           }
  1198.         }
  1199.       ]]>      
  1200.       </handler>
  1201.     </handlers>
  1202.   </binding>
  1203.           
  1204.   <binding id="panebutton" extends="chrome://global/content/bindings/radio.xml#radio">
  1205.     <resources>
  1206.       <stylesheet src="chrome://global/skin/preferences.css"/>
  1207.     </resources>
  1208.     <content>
  1209.       <xul:image class="paneButtonIcon" xbl:inherits="src"/>
  1210.       <xul:label class="paneButtonLabel" xbl:inherits="value=label"/>
  1211.     </content>
  1212.     <implementation implements="nsIAccessible">
  1213.       <property name="accessibleType" readonly="true">
  1214.         <getter>
  1215.           <![CDATA[
  1216.             return Components.interfaces.nsIAccessibleProvider.XULListitem;
  1217.           ]]>
  1218.         </getter>
  1219.       </property>
  1220.     </implementation>
  1221.   </binding>
  1222.  
  1223. </bindings>
  1224.  
  1225.  
  1226.